namespace Xmef.Engine
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using Xmef.Engine.Internal;
    using Xmef.Interfaces;
    using Xmef.Library;

    [Serializable]
    public class PluginCollectionContainer : PluginIdentity, IPluginCollectionContainer, IPluginIdentity
    {
        private Hashtable _hosts = new Hashtable();

        public void AddHost(string name, IPluginConfiguration host)
        {
            if (!this._hosts.ContainsKey(name))
            {
                this._hosts.Add(name, host);
            }
        }

        public IEnumerable<IPluginObject> GetActivePlugins(Predicate<IPluginObject> match)
        {
            foreach (IPluginObject plugin in ActivePlugins)
            {
                if (match(plugin))
                {
                    yield return plugin;
                }
            }
        }

        public static IPluginObjectCollection<T> GetActivePlugins<T>(IPluginHostManager container)
        {
            PluginObjectCollection<T> plugins = new PluginObjectCollection<T>();
            foreach (IPluginObjectInternal plugin in container.ActivePlugins)
            {
                IPluginObject<T> obj = plugin as IPluginObject<T>;
                if (obj != null)
                {
                    plugins.Add(obj);
                }
            }
            return plugins;
        }

        public IPluginConfiguration GetHost(string hostName)
        {
            if (this._hosts.ContainsKey(hostName))
            {
                return (IPluginConfiguration) this._hosts[hostName];
            }
            return null;
        }

        public IEnumerable<IPluginObject> GetLoadedPlugins(Predicate<IPluginObject> match)
        {
            foreach (IPluginObject plugin in LoadedPlugins)
            {
                if (match(plugin))
                {
                    yield return plugin;
                }
            }
        }

        public static IPluginObjectCollection<T> GetLoadedPlugins<T>(IPluginHostManager container)
        {
            PluginObjectCollection<T> plugins = new PluginObjectCollection<T>();
            foreach (IPluginObject plugin in container.LoadedPlugins)
            {
                IPluginObject<T> obj = plugin as IPluginObject<T>;
                if (obj != null)
                {
                    plugins.Add(obj);
                }
            }
            return plugins;
        }

        public void RemoveHost(string name, IPluginConfiguration host)
        {
            if (this._hosts.ContainsKey(name))
            {
                this._hosts.Remove(name);
            }
        }

        public IEnumerable<IPluginObject> ActivePlugins
        {
            get
            {
                IEnumerable<IPluginConfiguration> hosts = Hosts;
                if (hosts != null)
                {
                    foreach (IPluginConfiguration host in hosts)
                    {
                        foreach (IPluginObject plugin in host.ActivePlugins)
                        {
                            yield return plugin;
                        }
                    }
                }
            }
        }

        public int Count
        {
            get
            {
                int count = 0;
                IEnumerable<IPluginConfiguration> hosts = this.Hosts;
                if (hosts != null)
                {
                    foreach (IPluginConfiguration host in hosts)
                    {
                        count += host.Count;
                    }
                }
                return count;
            }
        }

        public IEnumerable<IPluginConfiguration> Hosts
        {
            get
            {
                foreach (IPluginConfiguration host in _hosts.Values)
                {
                    yield return host;
                }
            }
        }

        public IEnumerable<IPluginObject> LoadedPlugins
        {
            get
            {
#if CODE_CONTRACTS
                CodeContract.Assume(Hosts != null); 
#endif
                IEnumerable<IPluginConfiguration> hosts = Hosts;
                if (hosts != null)
                {
                    foreach (IPluginConfiguration host in hosts)
                    {
                        foreach (IPluginObject plugin in host.LoadedPlugins)
                        {
                            yield return plugin;
                        }
                    }
                }
            }
        }
    }
}

